﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CmdCreateStructurePlate.h"
#include "IInstanceType.h"
#include "OwnerPtr.h"
#include "IEditMode.h"
#include "IStructureEditModeBehavior.h"
#include "StructureInstancePresetParameterUtils.h"
#include "IFamily.h"
#include "StructureFamilyUtils.h"
#include "IUserTransaction.h"
#include "StructureCmdParamIds.h"
#include "ICommandManager.h"
#include "IUiDocument.h"
#include "UserTransactionGroupUtils.h"
#include "GbmpPresetParameterUIUtils.h"
#include "CmdStatusUtils.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

gcmp::CmdCreateStructurePlateBase::CmdCreateStructurePlateBase(const std::wstring& commandId)
    : GbmpCommandBase(commandId)
{
}

bool gcmp::CmdCreateStructurePlateBase::IsEnabled() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT
}

bool gcmp::CmdCreateStructurePlateBase::IsVisible() const
{
    CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT
}

bool gcmp::CmdCreateStructurePlateBase::ResetCommand()
{
    m_familyId = ElementId::InvalidID;
    m_instanceTypeId = ElementId::InvalidID;

    return true;
}

gcmp::OwnerPtr<gcmp::IAction> gcmp::CmdCreateStructurePlateBase::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    if (!CheckRunTimeEnvironment())
    {
        return nullptr;
    }
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    // 创建内建楼板/筏形基础族
    StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators = this->GetDefaultFamilyCreators();
    StructureFamilyUiUtils::CreateFamilies(pDoc, defaultFamilyCreators);

    // 获取新创建实例的族名称、实例类型
    std::wstring familyName;
    std::wstring instanceType;
    {
        // 从命令参数读取
        auto itor = cmdParams.find(ID_CMD_PARAM_FAMILY_NAME);
        if (itor != cmdParams.end())
        {
            familyName = itor->second.AsWString();
        }
        itor = cmdParams.find(ID_CMD_PARAM_INSTANCE_TYPE);
        if (itor != cmdParams.end())
        {
            instanceType = itor->second.AsWString();
        }
    }
    if (familyName.empty() || instanceType.empty())
    {
        StructureInstancePresetParameterUtils::GetPresetFamilyNameAndInstanceType(pDoc, this->GetCategory(),
            this->GetCategorySecondKey(), familyName, instanceType);
    }
    if (familyName.empty())
    {
        familyName = GetDefaultFamilyName();
    }
    const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");

    if (instanceType.empty())
    {
        bool bOk = StructureFamilyUtils::GetFirstInstanceType(pFamily, instanceType);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"GetFirstInstanceType失败",L"GDMPLab",L"2024-03-30");
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!instanceType.empty(), L"instanceType为空",L"GDMPLab",L"2024-03-30");

    const IInstanceType* pInstanceType = pFamily->GetInstanceTypeByName(instanceType);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    this->SetFamilyIdAndInstanceTypeId(pFamily->GetElementId(), pInstanceType->GetElementId());

    int groupId;
    UserTransactionGroupUtils::Start(pDoc, GBMP_TR(L"绘制轮廓"), groupId);
    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"开始绘制轮廓"));

    ElementId presetElementId = CreateTempPresetElement();
    DBG_WARN_AND_RETURN_UNLESS(presetElementId.IsValid(), nullptr, L"presetElementId无效",L"GDMPLab",L"2024-03-30");

    IEditMode* pProfileEditMode = PrepareEditMode(pDoc);
    DBG_WARN_AND_RETURN_UNLESS(pProfileEditMode != nullptr, nullptr, L"pProfileEditMode为空",L"GDMPLab",L"2024-03-30");

    IStructureEditModeBehavior* pProfileBehavior = quick_cast<IStructureEditModeBehavior>(pProfileEditMode->GetEditModeBehavior());
    DBG_WARN_AND_RETURN_UNLESS(pProfileBehavior != nullptr, nullptr, L"pProfileBehavior为空",L"GDMPLab",L"2024-03-30");

    pProfileBehavior->SetEditingFamilyId(pFamily->GetElementId());
    pProfileBehavior->SetEditingInstanceTypeId(pInstanceType->GetElementId());
    pProfileBehavior->SetPresetElementId(presetElementId);

    pProfileEditMode->StartEditing(pDoc, ElementId::InvalidID, true, false);

    opTransaction->Commit();

    // 更新属性面板
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(presetElementId);

    UiDocumentViewUtils::GetCurrentUiDocument()->UpdateView();

    // 启动进入编辑模式的首个命令
    ICommandManager* pCommandManager = ICommandManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCommandManager, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    pCommandManager->SendCommand(GetInitialCommandId());

    return nullptr;
}


bool gcmp::CmdCreateStructurePlateBase::SetFamilyIdAndInstanceTypeId(ElementId familyId, ElementId instanceTypeId)
{
    if (m_familyId.HasSameValue(familyId) && m_instanceTypeId.HasSameValue(instanceTypeId))
        return true;

    m_familyId = familyId;
    m_instanceTypeId = instanceTypeId;

    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"保存当前创建实例的族类型到预设参数"), true);

    bool bOk = StructureInstancePresetParameterUtils::SetPresetInstanceType(pDoc, this->GetCategory(), this->GetCategorySecondKey(), m_instanceTypeId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"SetPresetInstanceType失败",L"GDMPLab",L"2024-03-30");

    opTransaction->Commit();

    return true;
}
